package com.longrise.android.byjk.plugins.dealsituation.course.video2.education.insurance.videocontroller;

import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Handler;
import android.os.Message;
import android.view.GestureDetector;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.AlphaAnimation;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.TextView;


import com.longrise.android.byjk.R;
import com.longrise.android.byjk.plugins.dealsituation.course.video2.media.IjkVideoView;
import com.longrise.common.utils.NetUtil;

import java.util.Formatter;
import java.util.Locale;

import tv.danmaku.ijk.media.player.IMediaPlayer;


/**
 * Created by godliness on 2017/8/23.
 *
 * @author sujizhong
 *         控制播放过程
 *         1、加载资源
 *         2、初始化完成
 *         3、播放，暂停，出错，当前进度，总时长等等
 *         4、缓冲
 *         5、重试
 *         等相关控制逻辑
 */

public class VideoController extends BaseController implements View.OnClickListener,
        View.OnTouchListener, SeekBar.OnSeekBarChangeListener, IMediaPlayer.OnInfoListener,
        IMediaPlayer.OnCompletionListener, IMediaPlayer.OnErrorListener, IMediaPlayer.OnPreparedListener {

    private static final String TAG = "VideoController";

    private static final int mDefalutOutTime = 3000;

    private final int UPDATE_PROGRESS_MSG = 0;
    private final int HIDE_MSG = 1;

    private StringBuilder mFormatBuilder;
    private Formatter mFormatter;

    private OnProgressInterface mProgressListener;

    private GestureDetector mGestureDetector;

    private View mRootView;

    private View mHaze;
    private View mUnableBack;

    /**
     * 标题栏
     */
    private View mTitleBar;
    private View mBack;
    private TextView mTvTitle;

    /**
     * 进度控制栏
     */
    private View mControllerBar;
    private SeekBar mProgress;
    private View mPauseOrStart;
    private ImageView mPause;
    private TextView mEnd;
    private TextView mCurrent;
    private View mRecord;

    /**
     * 缓冲区域
     */
    private View mLoading;
    private TextView mTvInfor;
    private TextView mTvReset;

    private boolean mShowing = true;
    private boolean mHandPause;
    private boolean mCompleted;

    /**
     * 断点  seekTo()
     */
    private int mCurrentPosition = 0;

    private long mNewposition;

    public VideoController() {
        mFormatBuilder = new StringBuilder();
        mFormatter = new Formatter(mFormatBuilder, Locale.getDefault());
    }

    /**
     * 添加控制栏
     */
    @Override
    public void addVideoController(IjkVideoView videoView) {
        super.addVideoController(videoView);
        initControllerView(LayoutInflater.from(getContext()));
        thisAttachToVideo();
        regEvent(true);
    }

    public void addProgressListener(OnProgressInterface progressListener) {
        this.mProgressListener = progressListener;
    }

    protected View getControllerRootView() {
        return mRootView;
    }

    /**
     * VideoController是否显示
     */
    public boolean isShowing() {
        return mShowing;
    }

    /**
     * 设置当前播放进度
     */
    public boolean seekTo(int progress) {
        if (notNull()) {
            get().seekTo(progress);
            return true;
        }
        return false;
    }

    /**
     * 获取当前进度
     */
    public int getCurrentPosition() {
        if (notNull()) {
            return get().getCurrentPosition();
        }
        return 0;
    }

    /**
     * 设置当前进度 仅仅修改值 该方法在setVideoPath()之前调用，会在初始化完成时使用
     */
    public void setCurrentPosition(int currentPosition) {
        this.mCurrentPosition = currentPosition;
    }

    public int getDuration() {
        if (notNull()) {
            return get().getDuration();
        }
        return 0;
    }

    public int getBufferPercentage() {
        if (notNull()) {
            return get().getBufferPercentage();
        }
        return 0;
    }

    public boolean isPlaying() {
        if (notNull()) {
            return get().isPlaying();
        }
        return false;
    }

    public boolean pause() {
        if (notNull()) {
            get().pause();
            return true;
        }
        return false;
    }

    public boolean start() {
        if (notNull()) {
            get().start();
            return true;
        }
        return false;
    }

    /**
     * 设置课件标题
     */
    public void setTitle(String text) {
        if (mTvTitle != null) {
            mTvTitle.setText(text);
        }
    }

    /**
     * @param position 断点进度 当加载初始化完成，onPrepared() 会 seekTo(mCurrentPosition)
     * @param url      播放地址
     */
    public void setVideoPath(int position, String url) {
        if (notNull()) {
            this.mCurrentPosition = position;
            get().setVideoPath(url);
        }
    }

    /**
     * 设置播放地址
     */
    public void setVideoPath(String url) {
        if (notNull()) {
            get().setVideoPath(url);
        }
    }

    public void setVideoURI(int position, Uri uri) {
        if (notNull()) {
            this.mCurrentPosition = position;
            get().setVideoURI(uri);
        }
    }

    /**
     * 缓冲状态
     *
     * @param isLoading 是否正在缓冲
     */
    public void buffering(boolean isLoading) {
        bufferState(isLoading);
        inforState(false, "");
        resetState(false);
    }

    /**
     * 异常状态
     *
     * @param exception     是否是异常状态
     * @param exceptionText 异常状态时，界面提示语言
     */
    public void exception(boolean exception, String exceptionText) {
        setControllerEnable(!exception);//取反，如果出错，则Enable
        setHaze(true, false);
        hide();
        bufferState(false);
        resetState(exception);
        inforState(exception, exceptionText);
        mHandPause = true;
    }

    /**
     * @param enable 是否允许弹出控制栏
     */
    public void setControllerEnable(boolean enable) {
        if (notNull()) {
            get().setEnabled(enable);
        }
        if (mUnableBack != null) {
            mUnableBack.setVisibility(enable ? View.GONE : View.VISIBLE);
        }
    }

    /**
     * 完成时状态
     *
     * @param completeText 完成时状态，界面提示语
     */
    public void complete(String completeText) {
        inforState(true, completeText);
        bufferState(false);
        resetState(false);
        setHaze(false, true);
        mHandPause = true;
    }

    /**
     * 初始化完成状态
     */
    public void initPrepared() {
        buffering(false);
        inforState(false, "");
        resetState(false);
        clearHaze(true);
        setControllerEnable(true);
    }

    /**
     * 显示控制栏，隐藏为自动控制
     */
    public void show() {
        show(mDefalutOutTime);
    }

    /**
     * 隐藏控制栏
     */
    public void hide() {
        if (mShowing && isAnchor()) {
            smoothTransition(false);
            smoothAlpha(false);
            mShowing = false;
        }
        if (mHandler != null) {
            mHandler.removeMessages(HIDE_MSG);
            mHandler.removeMessages(UPDATE_PROGRESS_MSG);
        }
    }

    /**
     * 添加遮幕效果
     *
     * @param haze          VideoController是否能够enable
     * @param openAnimation 是否开启动画
     */
    public void setHaze(boolean haze, boolean openAnimation) {
        hide();
        pause();
        setControllerEnable(!haze); //取反

        if (mHaze != null) {
            mHaze.setVisibility(View.VISIBLE);

            if (openAnimation) {
                AlphaAnimation alphaVisiable = alphaTo(100, 0, 1);
                mHaze.setAnimation(alphaVisiable);
                alphaVisiable.start();
            }
        }
    }

    /**
     * 清除遮幕
     *
     * @param openAnimation 是否开启过渡效果
     */
    public void clearHaze(boolean openAnimation) {
        inforState(false, "");

        if (mHaze != null) {
            mHaze.setVisibility(View.GONE);

            if (openAnimation) {
                AlphaAnimation alphaHaze = alphaTo(100, 1, 0);
                mHaze.setAnimation(alphaHaze);
                alphaHaze.start();
            }
        }
    }

    /**
     * 设置进度条是否允许拖动 clickEnable影响onTouchEvent()
     */
    public void setProgressEnable(boolean enable) {
        if (mProgress != null) {
            mProgress.setEnabled(enable);
        }
    }

    private void bufferState(boolean isLoading) {
        if (mLoading != null) {
            mLoading.setVisibility(isLoading ? View.VISIBLE : View.GONE);
        }
    }

    private void inforState(boolean visiable, String inforText) {
        if (mTvInfor != null) {
            mTvInfor.setVisibility(visiable ? View.VISIBLE : View.GONE);
            mTvInfor.setText(inforText);
        }
    }

    private void resetState(boolean visiable) {
        if (mTvReset != null) {
            mTvReset.setVisibility(visiable ? View.VISIBLE : View.GONE);
        }
    }

    private boolean isAnchor() {
        return mTitleBar != null && mControllerBar != null;
    }

    private void initTitleBar() {
        if (mTitleBar == null) {
            mHaze = mRootView.findViewById(R.id.view_haze);
            mUnableBack = mRootView.findViewById(R.id.rl_unable_back);
            mTitleBar = mRootView.findViewById(R.id.video_title_layout);
            mBack = mRootView.findViewById(R.id.rl_back_left);
            mTvTitle = (TextView) mRootView.findViewById(R.id.tv_title);
        }
    }

    private void initControllerBar() {
        if (mControllerBar == null) {
            mControllerBar = mRootView.findViewById(R.id.rl_video_progress);
            mProgress = (SeekBar) mRootView.findViewById(R.id.video_controller);
            mPauseOrStart = mRootView.findViewById(R.id.pause);
            mPause = (ImageView) mRootView.findViewById(R.id.iv_pause);
            mEnd = (TextView) mRootView.findViewById(R.id.end);
            mCurrent = (TextView) mRootView.findViewById(R.id.progress);
            mRecord = mRootView.findViewById(R.id.courselist);
        }
    }

    private void initLoadView() {
        if (mLoading == null) {
            mLoading = mRootView.findViewById(R.id.ll_loading);
            mTvInfor = (TextView) mRootView.findViewById(R.id.tv_infor);
            mTvReset = (TextView) mRootView.findViewById(R.id.tv_exception_btn);
        }
    }

    private void thisAttachToVideo() {
        if (notNull()) {
            get().addView(mRootView);
        }
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.rl_back_left:
                if (mProgressListener != null) {
                    mProgressListener.onBack();
                }
                break;

            case R.id.rl_unable_back:
                if (mProgressListener != null) {
                    mProgressListener.onBack();
                }
                break;

            case R.id.pause:
                doPausePlay();
                break;

            case R.id.courselist:
                if (mProgressListener != null) {
                    mProgressListener.onRecord();
                }
                break;

            case R.id.tv_exception_btn:
                if (mProgressListener != null) {
                    mProgressListener.onReset();
                }
                break;

            default:
                break;
        }
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if (mGestureDetector != null) {
            mGestureDetector.onTouchEvent(event);
        }
        return true;
    }

    @Override
    public void onCompletion(IMediaPlayer iMediaPlayer) {
        if (mProgressListener != null) {
            mProgressListener.onComplete();
        }
        mCompleted = true;
    }

    @Override
    public boolean onError(IMediaPlayer iMediaPlayer, int i, int i1) {
        if (mProgressListener != null) {
            mProgressListener.onVideoError();
        }
        return true;
    }

    @Override
    public void onPrepared(IMediaPlayer iMediaPlayer) {
        seekTo(mCurrentPosition);
        if (isShowing()) {
            show();
        }

        //这里主要防止后台start()
        if (mProgressListener != null && mProgressListener.onPrepared()) {
            start();
        }

        if (mHandler != null) {
            mHandler.removeCallbacks(mInitRunnable);
            mHandler.postDelayed(mInitRunnable, 1000);
        }
        mCompleted = false;
    }

    private Runnable mInitRunnable = new Runnable() {
        @Override
        public void run() {
            initPrepared(); //delay 1s 用于屏蔽画面过渡
        }
    };

    /**
     * 缓冲结束时
     *
     * @param isNetWork 是否有网络连接
     */
    private void onBufferingEnd(boolean isNetWork) {
        if (isNetWork) {
            if (isPlaying() || mHandPause) {
                buffering(false);
            }
            return;
        }
        exception(true, "😭️ 当前无网络连接...");
        if (mProgressListener != null) {
            mProgressListener.onVideoError();
        }
    }

    @Override
    public boolean onInfo(IMediaPlayer iMediaPlayer, int what, int i1) {
        switch (what) {
            case MediaPlayer.MEDIA_INFO_BUFFERING_START:
                buffering(true);
                mHandPause = true;
                break;

            case MediaPlayer.MEDIA_INFO_BUFFERING_END:
                boolean isNetWork = false;
                try {
                    isNetWork = NetUtil.checkNetEnable();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                onBufferingEnd(isNetWork);
                break;

            default:
                break;
        }
        return true;
    }

    @Override
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
        if (!fromUser) {
            return;
        }

        long duration = getDuration();
        mNewposition = (duration * progress) / 1000L;
        if (mCurrent != null) {
            mCurrent.setText(stringForTime((int) mNewposition));
        }

    }

    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {
        show(3600000);

        if (mHandler != null) {
            mHandler.removeMessages(UPDATE_PROGRESS_MSG);
        }
    }

    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {
        seekTo((int) mNewposition);

        setProgress();
        updatePausePlay();
        show(mDefalutOutTime);

        if (mHandler != null) {
            mHandler.sendEmptyMessage(UPDATE_PROGRESS_MSG);
        }

        mCompleted = false;
    }

    private void initControllerView(LayoutInflater inflater) {
        mRootView = inflater.inflate(R.layout.layout_video_controller, null, false);
        mRootView.setBackgroundColor(mRootView.getResources().getColor(android.R.color.transparent));
        initTitleBar();
        initControllerBar();
        initLoadView();
    }

    private void regEvent(boolean isClick) {
        if (mTitleBar != null) { //主要用于拦截事件
            mTitleBar.setOnClickListener(isClick ? this : null);
        }
        if (mControllerBar != null) { //主要用于拦截事件
            mControllerBar.setOnClickListener(isClick ? this : null);
        }
        if (mBack != null) {
            mBack.setOnClickListener(isClick ? this : null);
        }
        if (mUnableBack != null) {
            mUnableBack.setOnClickListener(isClick ? this : null);
        }
        if (mRecord != null) {
            mRecord.setOnClickListener(isClick ? this : null);
        }
        if (mPauseOrStart != null) {
            mPauseOrStart.setOnClickListener(isClick ? this : null);
        }
        if (notNull()) {
            get().setOnPreparedListener(isClick ? this : null);
            get().setOnCompletionListener(isClick ? this : null);
            get().setOnInfoListener(isClick ? this : null);
            get().setOnErrorListener(isClick ? this : null);
            get().setOnTouchListener(isClick ? this : null);
        }
        if (mTvReset != null) {
            mTvReset.setOnClickListener(isClick ? this : null);
        }
        if (mProgress != null) {
            mProgress.setOnSeekBarChangeListener(isClick ? this : null);
        }
        if (isClick) {
            registerGesture();
        } else {
            mGestureDetector = null;
            mSimpleListener = null;
        }
    }

    private void registerGesture() {
        mGestureDetector = new GestureDetector(getContext(), mSimpleListener);
    }

    /**
     * 播放/暂停
     */
    private void doPausePlay() {
        if (mPause == null) {
            return;
        }
        if (isPlaying()) {
            pause();
            mHandPause = true;
            setPlayBtnDrawable(android.R.drawable.ic_media_play);
        } else {
            start();
            mHandPause = false;
            setPlayBtnDrawable(android.R.drawable.ic_media_pause);
        }

        clearHaze(false);

        if (isShowing()) {
            show();
        }
        mCompleted = false;
    }

    private void setPlayBtnDrawable(int drawable) {
        mPause.setImageDrawable(mPause.getResources().getDrawable(drawable));
    }

    /**
     * show 控制栏
     */
    public void show(int timeOut) {
        if (!mShowing && isAnchor()) {
//            setProgress();
            smoothTransition(true);
            smoothAlpha(true);
            mShowing = true;
        }
        if (mHandler != null) {
            mHandler.sendEmptyMessage(UPDATE_PROGRESS_MSG);

            Message msg = mHandler.obtainMessage(HIDE_MSG);
            if (timeOut != 0) {
                mHandler.removeMessages(HIDE_MSG);
                mHandler.sendMessageDelayed(msg, timeOut);
            }
        }

        updatePausePlay();

    }

    private void smoothTransition(boolean visiable) {
        if (mControllerBar != null && mTitleBar != null) {
            mControllerBar.setVisibility(visiable ? View.VISIBLE : View.GONE);
            mTitleBar.setVisibility(visiable ? View.VISIBLE : View.GONE);
        }
    }

    private void smoothAlpha(boolean visiable) {
        if (mControllerBar != null && mTitleBar != null) {
            AlphaAnimation mShow = visiable ? alphaTo(300, 0, 1) : alphaTo(300, 1, 0);
            mControllerBar.setAnimation(mShow);
            mTitleBar.setAnimation(mShow);
            mShow.start();
        }
    }

    private void updatePausePlay() {
        if (mPause != null) {
            mPause.setImageDrawable(isPlaying() ? mPause.getResources().getDrawable(android.R.drawable.ic_media_pause) : mPause.getResources().getDrawable(android.R.drawable.ic_media_play));
        }
    }

    /**
     * 毫秒转时分秒
     */
    private String stringForTime(int timeMs) {
        int totalSeconds = timeMs / 1000;

        int seconds = totalSeconds % 60;
        int minutes = (totalSeconds / 60) % 60;
        int hours = totalSeconds / 3600;

        mFormatBuilder.setLength(0);
        if (hours > 0) {
            return mFormatter.format("%d:%02d:%02d", hours, minutes, seconds).toString();
        } else {
            return mFormatter.format("%02d:%02d", minutes, seconds).toString();
        }
    }

    /**
     * 设置进度
     */
    private int setProgress() {
        int duration = getDuration();
        int position = getCurrentPosition();

        //播放完成时，获取到的position总是少于duration（一般在1000ms以内），在不同硬件平台表现略有差异。根据具体差异做处理
        if (mCompleted) {
            int value = duration - position;
            if (value > 0 && value <= 1000) {
                position += value;
            }
        }

        if (mProgress != null) {
            if (duration > 0) {
                long pos = 1000L * position / duration;  //temporary add 558
                mProgress.setProgress((int) pos);
            }
            int percent = getBufferPercentage();
            mProgress.setSecondaryProgress(percent * 10);
        }

        if (mEnd != null) {
            mEnd.setText("/" + stringForTime(duration));
        }
        if (mCurrent != null) {
            mCurrent.setText(stringForTime(position));
        }
        return position;
    }

    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case HIDE_MSG:
                    hide();
                    break;

                case UPDATE_PROGRESS_MSG:
                    int pos = setProgress();
                    if (mShowing && isPlaying()) {
                        msg = obtainMessage(UPDATE_PROGRESS_MSG);
                        sendMessageDelayed(msg, 1000 - (pos % 1000));
                    }
                    break;

                default:
                    break;
            }
        }
    };

    private GestureDetector.SimpleOnGestureListener mSimpleListener = new GestureDetector.SimpleOnGestureListener() {

        @Override
        public boolean onSingleTapConfirmed(MotionEvent e) {
            if (isShowing()) {
                hide();
            } else {
                show();
            }
            return false;
        }

        @Override
        public boolean onDoubleTap(MotionEvent e) {
            doPausePlay();
            return false;
        }
    };

    /**
     * 释放资源
     */
    public void release() {
        if (mHandler != null) {
            mHandler.removeCallbacksAndMessages(null);
        }
        regEvent(false);
    }

    public interface OnProgressInterface {

        /**
         * 标题栏back
         */
        void onBack();

        /**
         * 目录
         */
        void onRecord();

        /**
         * 当前课件初始化完成时回调 return 当前Activity是否onResume()
         */
        boolean onPrepared();

        /**
         * 当前课件播放完成时回调
         */
        void onComplete();

        /**
         * 当前课件播放过程中，出错回调
         */
        void onVideoError();

        /**
         * 点击重试
         */
        void onReset();

    }
}
